package edu.kit.aifb.ldstream.repository.listeners;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import org.openrdf.model.impl.URIImpl;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFParseException;

import edu.kit.aifb.ldstream.env.Environment;

/**
 * Listener thread which listens to a N3-file and save the content to the global
 * repository.
 */

public class FileListeningThread extends AbstractListeningThread {

	private static int numListeners = 0;

	private String filePath;
	private RDFFormat format;
	private BufferedWriter errorLogWriter;

	private int numEvents = 0;

	public FileListeningThread(String filePath, String baseURI){
		super(baseURI);
		this.filePath = filePath;
		File errorFile = new File("./errorLog" + numListeners + ".log");
		numListeners++;
		if(errorFile.exists()){
			errorFile.delete();
		}
		try {
			errorFile.createNewFile();
		} catch (IOException e) {}

		try {
			this.errorLogWriter = new BufferedWriter(new FileWriter(errorFile));
		} catch (IOException e) {}


		if(new File(filePath).isDirectory()){
			this.format = RDFFormat.N3;
		}else{
			this.format = getRDFFormat(filePath);
		}


	}

	/**
	 * 
	 * @param filePath
	 *            of the N3 formatted file.
	 * @param baseURI
	 *            of the file.
	 */
	public FileListeningThread(String filePath, String baseURI, RDFFormat format) {
		super(baseURI);
		this.filePath = filePath;
		this.format = format;
	}

	public void run() {
		String currentFile = "";
		try {
			RepositoryConnection con = Environment.REPO.getConnection();
			con.setAutoCommit(false);
			try {
				if(Environment.VERBOSE){
					System.out.println("Starting to read " + filePath + "with the format " + format.toString());
				}
				if(this.format != null){


					File f = new File(filePath);
					if(f.isDirectory()){
						String[] files = f.list();
						for(String s : files){
							currentFile = s;
							if (Environment.VERBOSE) {
								System.out.println("Reading file " + s);
							}
							try{
								con.add(new BufferedReader(new FileReader(new File(filePath + s)), 1024 * 1024), this.baseURI,
										this.format, new URIImpl(Environment.EVENT_CONTEXT + AbstractListeningThread.EVENT_ID.getAndAdd(1)));
								this.numEvents++;
								con.commit();
							}catch(RDFParseException e){
								System.err.println("The file " + s + " containes RDF syntax errors");
								try {
									//write into error log
									this.errorLogWriter.write(currentFile);
								} catch (IOException e1) {}
							}
						}
					}else {
						if (Environment.VERBOSE) {
							System.out.println("Reading file " + filePath);
						}
						con.add(new BufferedReader(new FileReader(f), 1024 * 1024), this.baseURI,
								this.format, new URIImpl(Environment.EVENT_CONTEXT + AbstractListeningThread.EVENT_ID.getAndAdd(1)));
						this.numEvents++;
					}
					/*
					con.add(new FileReader(new File(filePath)), this.baseURI,
							this.format, con.getValueFactory().createURI(this.baseURI + "#" + getFileName()));
					 */
					if (Environment.VERBOSE) {
						System.out.println("File " + filePath
								+ " added to the repository");
					}
				}
			} catch (RDFParseException e) {
				System.err.println("The given file containes RDF syntax errors");
				try {
					this.errorLogWriter.write(currentFile);
				} catch (IOException e1) {
				}
			} catch (FileNotFoundException e) {
				System.err.println("The given file is not accessible");
			} catch (IOException e) {
			} finally {
				con.commit();
				con.close();
			}
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
	}

	@Override
	public int getNumEvents(){
		return this.numEvents;
	}

	private RDFFormat getRDFFormat(String fileName){
		int pos = fileName.lastIndexOf(".");
		String extension = fileName.substring(pos);

		if(extension.equals(".n3")){
			return RDFFormat.N3;
		}
		if(extension.equals(".nt")){
			return RDFFormat.NTRIPLES;
		}
		if(extension.equals(".trix")){
			return RDFFormat.TRIX;
		}
		if(extension.equals(".rdf")){
			return RDFFormat.RDFXML;
		}
		if(extension.equals(".ttl")){
			return RDFFormat.TURTLE;
		}
		if(extension.equals(".trig")){
			return RDFFormat.TRIG;
		}
		return RDFFormat.N3;
	}

	private String getFileName(){
		String s;
		int pos = this.filePath.lastIndexOf("/");
		if( pos != -1){
			s = this.filePath.substring(pos + 1);
		}else{
			pos = this.filePath.lastIndexOf("\\");
			s = this.filePath.substring(pos + 1);
		}

		return s;
	}

}
